#include "RbnNode.h"

#include <cstring>
using std::memcpy;

#include "../../base.h"
#include "../../qt/Logger.h"

namespace RBN {

RbnNode::RbnNode(int nInputs, int const* inputPositions, int const* function) :
	_nInputs(nInputs),
	_inputs(0) {

	/* input positions */
	_inputPositions = new int[nInputs];
	memcpy(_inputPositions, inputPositions, nInputs * sizeof(int));

	/* function */
	int functionSize = 1 << nInputs;
	_function = new int[functionSize];
	memcpy(_function, function, functionSize * sizeof(int));
}

RbnNode::~RbnNode() {
	delete[] _inputPositions;
	delete[] _inputs;
	delete[] _function;
}

void RbnNode::setInputsOutputs(int position, int const* inputs, int* outputs) {

	/* inputs : init */
	_inputs = new int const*[_nInputs];
	
	/* inputs : fill */
	for(int i = 0; i != _nInputs; ++i) {
		_inputs[i] = &(inputs[_inputPositions[i]]);
	}

	/* output */
	_output = &(outputs[position]);
}

void RbnNode::update() {

	/* function index : init */
	int index = 0;

	/* function index : compute */
	for(int i = 0; i != _nInputs; ++i) {
		index <<= 1;

		int input = *(_inputs[i]);
//		assert(input == (input & 1));
		if (input != 0 && input != 1) {
			Logger::error(QString("input should be 0 or 1, is : %1").arg(input));
		}
		index += input;
	}

	/* output */
	int functionOutput = _function[index];
	if (functionOutput != 0 && functionOutput != 1) {
		Logger::error(QString("functionOutput should be 0 or 1, is : %1").arg(functionOutput));
	}
	*_output = _function[index];
}

} // RBN

